#define _GNU_SOURCE
#define __USE_GNU
#include <stdio.h>
#include <sched.h>
#include <errno.h>
#include <unistd.h>
 
struct dt_struct {
	  unsigned short limit;
	    unsigned long base;
} __attribute__((packed));
 
void *get_sidt (void) {
	  struct dt_struct idt;
	    asm volatile ("sidt %0\t\n" : "=m"(idt));
	      return (void *)idt.base;
}
 
void *get_sgdt (void) {
	  struct dt_struct gdt;
	    asm volatile ("sgdt %0\t\n" : "=m"(gdt));
	      return (void *)gdt.base;
}
 
int main (void) {
	  int result = 0, cpu = 0, cpu2;
	    cpu_set_t cs, cs2;
	     
	      if (sched_getaffinity (getpid (), sizeof (cs), &cs) != 0) {
		          printf ("sched_getaffinity() failed : %m\n");
			      return -1;
			        }
	       
	        while (CPU_COUNT (&cs) != 0) {
			    if (CPU_ISSET (cpu, &cs)) {
				          CPU_ZERO (&cs2);
					        CPU_SET (cpu, &cs2);
						      if (sched_setaffinity (getpid (), sizeof (cs2), &cs2) != 0) {
							              printf ("setaffinity(%d) failed: %m\n", cpu);
								              result = 1;
									            }
						            else {
								            cpu2 = sched_getcpu ();
									            if (cpu2 == -1 && errno == ENOSYS) {
											              puts ("getcpu syscall not implemented");
												                return -1;
														        }
										            if (cpu2 != cpu) {
												              printf ("getcpu results %d not possible\n", cpu2);
													                result = 1;
															        }
											          }
							          printf ("CPU %d\nIDT : %p\nGDT : %p\n\n", cpu, get_sidt(), get_sgdt());
								        CPU_CLR (cpu, &cs);
									    }
			        ++cpu;
				  }
		  return 0;
}
